import { ESSceneObject } from 'earthsdk3';
import { defined, FeatureDetection, RuntimeError, TaskProcessor } from 'cesium';
class GaussianSplatSorter {
  static _maxSortingConcurrency = Math.max(
    //@ts-ignore
    FeatureDetection.hardwareConcurrency - 1,
    1,
  );;
  static _sorterTaskProcessor: TaskProcessor | undefined = undefined;
  static _taskProcessorReady = false;
  static _error: RuntimeError | undefined = undefined;
  static _getSorterTaskProcessor = function () {
    if (!defined(GaussianSplatSorter._sorterTaskProcessor)) {
      const processor = new TaskProcessor(
        // "gaussianSplatSorter",
        ESSceneObject.context.getStrFromEnv("${earthsdk3-assets-script-dir}/assets/gaussianSplatting/gaussianSplatSorter.js"),
        GaussianSplatSorter._maxSortingConcurrency,
      );
      processor
        .initWebAssemblyModule({
          wasmBinaryFile: ESSceneObject.context.getStrFromEnv("${earthsdk3-assets-script-dir}/assets/gaussianSplatting/wasm_splats_bg.wasm"),
        })
        .then(function (result) {
          if (result) {
            GaussianSplatSorter._taskProcessorReady = true;
          } else {
            GaussianSplatSorter._error = new RuntimeError(
              "Gaussian splat sorter could not be initialized.",
            );
          }
        })
        .catch((error) => {
          GaussianSplatSorter._error = error;
        });
      GaussianSplatSorter._sorterTaskProcessor = processor;
    }

    return GaussianSplatSorter._sorterTaskProcessor;
  };

  static radixSort = function (parameters: any) {
    const sorterTaskProcessor = GaussianSplatSorter._getSorterTaskProcessor();
    if (defined(GaussianSplatSorter._error)) {
      throw GaussianSplatSorter._error;
    }

    if (!GaussianSplatSorter._taskProcessorReady) {
      return;
    }

    return sorterTaskProcessor.scheduleTask(parameters, [
      parameters.primitive.attributes,
      parameters.primitive.modelView,
      parameters.primitive.count,
      parameters.sortType,
    ]);
  };

  static radixSortIndexes = function (parameters: any) {
    const sorterTaskProcessor = GaussianSplatSorter._getSorterTaskProcessor();
    if (defined(GaussianSplatSorter._error)) {
      throw GaussianSplatSorter._error;
    }

    if (!GaussianSplatSorter._taskProcessorReady) {
      return;
    }

    return sorterTaskProcessor.scheduleTask(parameters, [
      parameters.primitive.positions.buffer,
    ]);
  };
}

export default GaussianSplatSorter;